//
//  CameraComponent.m
//  XYLib
//
//  Created by Richard on 2019/1/3.
//  Copyright © 2019年 XY. All rights reserved.
//

#define KScreenWidth  [UIScreen mainScreen].bounds.size.width
#define KScreenHeight  [UIScreen mainScreen].bounds.size.height

// 宽度适配
#define ScalingStyle(Value) (Value*KScreenWidth/750);

// app名称
#define AppName [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]

//导入相机框架
#import <AVFoundation/AVFoundation.h>
#import <Photos/Photos.h>
//将拍摄好的照片写入系统相册中，所以我们在这里还需要导入一个相册需要的头文件iOS8
#import <Photos/Photos.h>
#import "CameraComponent.h"
@interface CameraComponent ()<UIAlertViewDelegate>
{
    CGRect scanRect;
}

@property (nonatomic,strong) AVCaptureSession *captureSession;
@property (nonatomic,strong) AVCaptureDeviceInput *deviceInput;
@property (nonatomic,strong) AVCaptureStillImageOutput *imageOutput;
@property (nonatomic,strong) AVCaptureVideoPreviewLayer *previewLayer;
@property (nonatomic,strong) AVCaptureDevice *captureDevice;
@property (nonatomic,strong) NSString *orientation;
@property (nonatomic,assign) CGFloat picTop;
@property (nonatomic,assign) CGFloat picLeft;
@property (nonatomic,assign) CGFloat picWidth;
@property (nonatomic,assign) CGFloat picHeight;
@property (nonatomic,assign) BOOL isSetCamera;//camera坐标是否自适应（没有传camera的坐标）
@property (nonatomic,assign) BOOL isCustomizePermission; // 自定义权限弹窗

@property (nonatomic,assign) CGFloat photo_original_w;
@property (nonatomic,assign) CGFloat photo_original_h;
@property (nonatomic,assign) CGFloat padding_iphoneX;




@end

@implementation CameraComponent

WX_EXPORT_METHOD(@selector(startCamera))
WX_EXPORT_METHOD(@selector(stopCamera))
WX_EXPORT_METHOD(@selector(shutterCamera:))
WX_EXPORT_METHOD(@selector(setFlashMode:))

- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance {
    self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance];
    if (self) {
//        if (attributes[@"isCustomizePermission"]) {
//            _isCustomizePermission = attributes[@"isCustomizePermission"];
//        } else {
//            _isCustomizePermission = NO;
//        }
        if (attributes[@"orientation"]) {
            _orientation = attributes[@"orientation"];
        }
        if (attributes[@"rectMake"] && attributes[@"rectMake"][@"top"]) {
            _picTop = [attributes[@"rectMake"][@"top"] floatValue] * self.weexInstance.pixelScaleFactor;
        }
        if (attributes[@"rectMake"] && attributes[@"rectMake"][@"left"]) {
            _picLeft = [attributes[@"rectMake"][@"left"] floatValue] * self.weexInstance.pixelScaleFactor;
        }
        if (attributes[@"rectMake"] && attributes[@"rectMake"][@"width"]) {
            _picWidth = [attributes[@"rectMake"][@"width"] floatValue] * self.weexInstance.pixelScaleFactor;
        }
        if (attributes[@"rectMake"] && attributes[@"rectMake"][@"height"]) {
            _picHeight = [attributes[@"rectMake"][@"height"] floatValue] * self.weexInstance.pixelScaleFactor;
        }
        if (_picTop == 0 && _picLeft == 0 &&_picWidth == 0 &&_picHeight == 0) {
            _isSetCamera = YES;
        }else{
            _isSetCamera = NO;
        }
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor clearColor];
    [self setUpCameraPreviewLayer];
    [self setFlashMode:AVCaptureFlashModeOff];
    [self startCamera];
    
    // 设置初始闪光灯为关闭状态
    if ([self.captureDevice lockForConfiguration:nil]) {
        if ([self.captureDevice isFlashModeSupported:AVCaptureFlashModeOff]) {
            [self.captureDevice setFlashMode:AVCaptureFlashModeOff];
        }
        [self.captureDevice unlockForConfiguration];
    }
    
}
- (void)setUpCameraPreviewLayer {
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    //相机权限无权限访问
    if ((authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) && (authStatus != AVAuthorizationStatusNotDetermined)) {

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"“%@”想访问您的相机", AppName]
                                                        message:@"开启后，可使用拍照拍摄功能"
                                                       delegate:self
                                              cancelButtonTitle:@"不允许"
                                              otherButtonTitles:@"好", nil];
        [alert show];
        
    }
    
    if (!_previewLayer) {
        [self initSession];
        self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
        self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspect;
        self.previewLayer.frame = CGRectMake((CGRectGetWidth(self.view.bounds)-KScreenWidth)/2, (CGRectGetHeight(self.view.bounds)-KScreenHeight)/2, KScreenWidth, KScreenHeight);
        if (!_isSetCamera) {
            if (@available(iOS 11.0, *)) {
                if (self.weexInstance.rootView.safeAreaInsets.top > 20) {
                    self.previewLayer.frame = CGRectMake(0, - self.padding_iphoneX, KScreenWidth, KScreenHeight);
                }
            }
        }
        [self.view.layer insertSublayer:self.previewLayer atIndex:0];
        
        
    }
    self.view.layer.masksToBounds = YES;
}

- (void)initSession {
//    self.captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    self.captureDevice = [self cameraWithDirection:AVCaptureDevicePositionBack];
    self.captureSession = [[AVCaptureSession alloc] init];
    if ([self.captureSession canSetSessionPreset:AVCaptureSessionPreset1920x1080]) {
        [self.captureSession setSessionPreset:AVCaptureSessionPreset1920x1080];
    }
    self.deviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:self.captureDevice error:nil];
    self.imageOutput = [[AVCaptureStillImageOutput alloc]init];
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil];
    [self.imageOutput setOutputSettings:outputSettings];
    if ([self.captureSession canAddInput:self.deviceInput]) {
        [self.captureSession addInput:self.deviceInput];
    }
    if ([self.captureSession canAddOutput:self.imageOutput]) {
        [self.captureSession addOutput:self.imageOutput];
    }
}

- (AVCaptureDevice *)cameraWithDirection:(AVCaptureDevicePosition)position {
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *device in devices) {
        if ([device position] == position) {
            return device;
        }
    }
    return nil;
}

- (void)startCamera
{
    if (self.captureSession) {
        [self.captureSession startRunning];
    }
}

- (void)stopCamera {
    if (self.captureSession) {
        [self.captureSession stopRunning];
    }
}

- (void)changeCamera{
    //获取摄像头的数量
    NSUInteger cameraCount = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];
    //摄像头小于等于1的时候直接返回
    if (cameraCount <= 1) return;
    
    AVCaptureDevice *newCamera = nil;
    AVCaptureDeviceInput *newInput = nil;
    //获取当前相机的方向(前还是后)
    AVCaptureDevicePosition position = [[self.deviceInput device] position];
    
    //为摄像头的转换加转场动画
    CATransition *animation = [CATransition animation];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.duration = 0.5;
    animation.type = @"oglFlip";
    
    if (position == AVCaptureDevicePositionFront) {
        //获取后置摄像头
        newCamera = [self cameraWithDirection:AVCaptureDevicePositionBack];
        animation.subtype = kCATransitionFromLeft;
    }else{
        //获取前置摄像头
        newCamera = [self cameraWithDirection:AVCaptureDevicePositionFront];
        animation.subtype = kCATransitionFromRight;
    }
    
    [self.previewLayer addAnimation:animation forKey:nil];
    //输入流
    newInput = [AVCaptureDeviceInput deviceInputWithDevice:newCamera error:nil];
    
    if (newInput != nil) {
        
        [self.captureSession beginConfiguration];
        //先移除原来的input
        [self.captureSession removeInput:self.deviceInput];
        if ([self.captureSession canAddInput:newInput]) {
            [self.captureSession addInput:newInput];
            self.deviceInput = newInput;
        } else {
            //如果不能加现在的input，就加原来的input
            [self.captureSession addInput:self.deviceInput];
        }
        [self.captureSession commitConfiguration];
    }
}

/*
 闪光灯
 */
- (BOOL)isOpenFlash {
    if ([self.captureDevice hasFlash] && [self.captureDevice hasTorch]) {
        if (self.captureDevice.torchMode == AVCaptureTorchModeOff) {
            [self.captureSession beginConfiguration];
            [self.captureDevice lockForConfiguration:nil];
            [self.captureDevice setTorchMode:AVCaptureTorchModeOn];
            [self.captureDevice setFlashMode:AVCaptureFlashModeOn];
            [self.captureDevice unlockForConfiguration];
            return YES;
        } else if (self.captureDevice.torchMode == AVCaptureTorchModeOn) {
            [self.captureSession beginConfiguration];
            [self.captureDevice lockForConfiguration:nil];
            [self.captureDevice setTorchMode:AVCaptureTorchModeOff];
            [self.captureDevice setFlashMode:AVCaptureFlashModeOff];
            [self.captureDevice unlockForConfiguration];
            return NO;
        }
        [self.captureSession commitConfiguration];
    }
    [self.captureSession stopRunning];
    return YES;
}


#pragma mark - 闪光灯
- (int)setFlashMode:(int)mode{
    if ([self.captureDevice hasFlash]) {
        switch (mode) {
            case 1:
                [self.captureSession beginConfiguration];
                [self.captureDevice lockForConfiguration:nil];
                [self.captureDevice setFlashMode:AVCaptureFlashModeOn];
                [self.captureDevice unlockForConfiguration];
                break;
            case 2:
                [self.captureSession beginConfiguration];
                [self.captureDevice lockForConfiguration:nil];
                [self.captureDevice setFlashMode:AVCaptureFlashModeAuto];
                [self.captureDevice unlockForConfiguration];
                break;
            default:
                [self.captureSession beginConfiguration];
                [self.captureDevice lockForConfiguration:nil];
                [self.captureDevice setFlashMode:AVCaptureFlashModeOff];
                [self.captureDevice unlockForConfiguration];
                break;
        }
        [self.captureSession commitConfiguration];
    }
    return (int)self.captureDevice.flashMode;
}

-(void)turnOnLed {
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if ([device hasTorch]) {
        [device lockForConfiguration:nil];
        [device setFlashMode:AVCaptureFlashModeOn];
        [device unlockForConfiguration];
    }
}

-(void)turnOffLed {
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if ([device hasTorch]) {
        [device lockForConfiguration:nil];
        [device setFlashMode:AVCaptureFlashModeOff];
        [device unlockForConfiguration];
    }
}


- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    
    if (buttonIndex == 1) {
        //引导开启
        NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        if ([[UIApplication sharedApplication]canOpenURL:url]) {
            [[UIApplication sharedApplication]openURL:url];
        }
    } else if (buttonIndex == 0) {
        [self fireEvent:@"cameraPermission" params:@{@"status": @"NO"}];
    }
    
}

#pragma mark- 拍照
- (void)shutterCamera:(WXCallback)callback
{
    AVCaptureConnection * videoConnection = [self.imageOutput connectionWithMediaType:AVMediaTypeVideo];
    if (videoConnection ==  nil) {
        return;
    }
    if ([_orientation isEqualToString:@"horizontal"]) {//横屏拍摄框
        videoConnection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;//控制输出照片方向
    }else{//竖屏拍摄框
        videoConnection.videoOrientation = AVCaptureVideoOrientationPortrait;//控制输出照片方向
    }
    
    [self.imageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
        
        if (imageDataSampleBuffer == nil) {
            return;
        }
//        NSString *tmpPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
        NSString *tmpPath = NSTemporaryDirectory();
        NSDate *date=[NSDate date];
        NSString* fileName = [NSString stringWithFormat:@"%ld.jpg",(long int)date.timeIntervalSince1970];
        NSString* filePath = [tmpPath stringByAppendingPathComponent:fileName];
        
        NSData *imageData =  [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        UIImage*image = [UIImage imageWithData:imageData];
        UIImage *image11 = [[UIImage alloc] init];
        if (_isSetCamera) {
            image11 =[self cropImage:[self fixOrientation:image]];
        }else{
            image11 = [self testImage:image];
        }
        NSData *fileImageData = UIImageJPEGRepresentation(image11, 0.5);
        NSString *pictureDataString=[fileImageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
        [fileImageData writeToFile:filePath atomically:YES];
        if (callback) {
            callback(@{@"path":[NSURL fileURLWithPath:filePath].absoluteString,@"file":pictureDataString});
        }
    }];
}

- (UIImage *)testImage:(UIImage *)image{
//    NSLog(@"image:%@",image);
    image = [self fixOrientation:image];
    CGFloat x = 0;
    CGFloat y = 0;
    CGFloat w = 0;
    CGFloat h = 0;
    CGFloat gap = (CGRectGetHeight(self.view.bounds)-KScreenHeight)/2;

        //横屏拍摄框
        x = (_picTop + 64 + gap)  * self.photo_original_w / KScreenHeight ;
        y = _picLeft * self.photo_original_h / KScreenWidth;
        w = _picHeight * self.photo_original_w / KScreenHeight ;
        h = _picWidth * self.photo_original_h / KScreenWidth ;
//        NSLog(@"x:%f",x);
    
    if (@available(iOS 11.0, *)) {
        CGFloat padding = self.padding_iphoneX;
        if (self.weexInstance.rootView.safeAreaInsets.top > 20) {
            x = (_picTop)  * self.photo_original_h / KScreenWidth ;
            y = (_picLeft) * self.photo_original_h / KScreenWidth;
            w = (_picHeight + padding/2 ) * self.photo_original_h / KScreenWidth ;
            h = (_picWidth + padding/2 ) * self.photo_original_h / KScreenWidth ;
//            NSLog(@"x:%f",x);
        }
    }
    image = [self getPartOfImageInRect:CGRectMake(x, y, w, h) image:image];
    return image;
}

- (UIImage *)getPartOfImageInRect:(CGRect)rect image:(UIImage *)image
{
    CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, rect);
    UIImage *thumbScale = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    return thumbScale;
}

// 以图片中心为中心,裁剪图片
-(UIImage *)cropImage:(UIImage *)image{
    
    CGImageRef sourceImageRef = [image CGImage];//将UIImage转换成CGImageRef
    
    CGFloat _imageWidth = image.size.width * image.scale;
    CGFloat _imageHeight = image.size.height * image.scale;
    CGFloat  width = _imageWidth * CGRectGetWidth(self.view.bounds)/KScreenWidth;
    CGFloat  height = _imageWidth * CGRectGetHeight(self.view.bounds)/KScreenWidth;
    if ([_orientation isEqualToString:@"horizontal"]) {//横屏拍摄框
        width = _imageWidth * CGRectGetHeight(self.view.bounds)/KScreenHeight;
        height = _imageWidth * CGRectGetWidth(self.view.bounds)/KScreenHeight;
        if (@available(iOS 11.0, *)) {
            if (self.weexInstance.rootView.safeAreaInsets.top > 20) {
                CGFloat safe = self.weexInstance.rootView.safeAreaInsets.top + self.weexInstance.rootView.safeAreaInsets.bottom;
                width = _imageWidth * CGRectGetHeight(self.view.bounds)/(KScreenHeight-safe*2);
                height = _imageWidth * CGRectGetWidth(self.view.bounds)/(KScreenHeight-safe*2);
            }
        }
        
    }
    
    CGRect rect = CGRectMake((_imageWidth - width)/2, (_imageHeight - height)/2, width, height);
    CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect);//按照给定的矩形区域进行剪裁
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
    
    return newImage;
}

// 判断图片是否翻转
- (UIImage *)fixOrientation:(UIImage *)aImage {
    
    // No-op if the orientation is already correct
    if (aImage.imageOrientation == UIImageOrientationUp)
        return aImage;
    
    // We need to calculate the proper transformation to make the image upright.
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
    CGAffineTransform transform = CGAffineTransformIdentity;
    
    switch (aImage.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
            
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;
            
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        default:
            break;
    }
    
    switch (aImage.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
            
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        default:
            break;
    }
    
    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,
                                             CGImageGetBitsPerComponent(aImage.CGImage), 0,
                                             CGImageGetColorSpace(aImage.CGImage),
                                             CGImageGetBitmapInfo(aImage.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (aImage.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);
            break;
            
        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage);
            break;
    }
    
    // And now we just create a new UIImage from the drawing context
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}

- (void)setBorderWithView:(UIView *)view top:(BOOL)top left:(BOOL)left bottom:(BOOL)bottom right:(BOOL)right borderColor:(UIColor *)color borderWidth:(CGFloat)width
{
    if (top) {
        CALayer *layer = [CALayer layer];
        layer.frame = CGRectMake(0, 0, view.frame.size.width, width);
        layer.backgroundColor = color.CGColor;
        [view.layer addSublayer:layer];
    }
    if (left) {
        CALayer *layer = [CALayer layer];
        layer.frame = CGRectMake(0, 0, width, view.frame.size.height);
        layer.backgroundColor = color.CGColor;
        [view.layer addSublayer:layer];
    }
    if (bottom) {
        CALayer *layer = [CALayer layer];
        layer.frame = CGRectMake(0, view.frame.size.height - width, view.frame.size.width, width);
        layer.backgroundColor = color.CGColor;
        [view.layer addSublayer:layer];
    }
    if (right) {
        CALayer *layer = [CALayer layer];
        layer.frame = CGRectMake(view.frame.size.width - width, 0, width, view.frame.size.height);
        layer.backgroundColor = color.CGColor;
        [view.layer addSublayer:layer];
    }
}
- (CGFloat)photo_original_h
{
    if (!_photo_original_h) {
        if ([self.captureSession canSetSessionPreset:AVCaptureSessionPreset1920x1080]) {
            self.photo_original_h = 1080;
        } else {
            self.photo_original_h = 1080;
        }
    }
    return _photo_original_h;
}

- (CGFloat)photo_original_w
{
    if (!_photo_original_w) {
        if ([self.captureSession canSetSessionPreset:AVCaptureSessionPreset1920x1080]) {
            self.photo_original_w = 1920;
        } else {
            self.photo_original_w = 1920;
        }
    }
    return _photo_original_w;
}

- (CGFloat)padding_iphoneX
{
    if (!_padding_iphoneX) {
        self.padding_iphoneX = (KScreenHeight - KScreenWidth * self.photo_original_w / self.photo_original_h)/2;
    }
    return _padding_iphoneX;
//    self.padding_iphoneX = (KScreenHeight - KScreenWidth * self.photo_original_w / self.photo_original_h)/2;
}
@end
